#include <cstdio>
inline int max(int H, int G) { return H > G ? H : G; }
inline int min(int H, int G) { return H < G ? H : G; }
inline void read(int &x) {
    x = 0;
    char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c & 15), c = getchar();
}
const int B = 3250;
int n, Q;
namespace Trie {
struct TrieNode {
    int ch[2], cnt;
} tr[5000007];
int tot = 0;
inline void insert(int x, int v, int &rt) {
    if (!rt)
        rt = ++tot;
    int u = rt;
    for (int i = 19; ~i; --i) {
        tr[u].cnt += v;
        if (!tr[u].ch[(x >> i) & 1])
            tr[u].ch[(x >> i) & 1] = ++tot;
        u = tr[u].ch[(x >> i) & 1];
    }
    tr[u].cnt += v;
}
inline int query(int x, int u) {
    int res = 0;
    for (int i = 19; ~i; --i)
        if (tr[tr[u].ch[((x >> i) & 1) ^ 1]].cnt)
            res |= (1 << i), u = tr[u].ch[((x >> i) & 1) ^ 1];
        else
            u = tr[u].ch[(x >> i) & 1];
    return res;
}
}  // namespace Trie
struct SecMax {
    int mx1, mx2;
    SecMax(int x1 = 0, int x2 = 0) { mx1 = x1, mx2 = x2; }
    inline void operator&=(const SecMax &rhs) {
        if (rhs.mx1 > mx1)
            mx2 = mx1, mx1 = rhs.mx1;
        else if (rhs.mx1 > mx2)
            mx2 = rhs.mx1;
        if (rhs.mx2 > mx2)
            mx2 = rhs.mx2;
    }
};
struct Block {
    int a[B + 2], siz, nxt, rt;
    SecMax val;
    Block() {
        for (int i = 0; i < B + 2; ++i) a[i] = 0;
        siz = nxt = rt = 0;
    }
    inline void maxize() {
        val = { 0, 0 };
        for (int i = 1; i <= siz; ++i) val &= { a[i], 0 };
    }
} b[77];
int cbl = 1;
inline void split(int x) {
    b[x].siz = b[++cbl].siz = B >> 1, b[cbl].nxt = b[x].nxt, b[x].nxt = cbl, b[x].rt = b[cbl].rt = 0;
    for (int i = 1; i <= (B >> 1); ++i)
        b[cbl].a[i] = b[x].a[i + (B >> 1)], b[x].a[i + (B >> 1)] = 0, Trie::insert(b[x].a[i], 1, b[x].rt),
        Trie::insert(b[cbl].a[i], 1, b[cbl].rt);
    b[x].maxize(), b[cbl].maxize();
}
inline void insert(int p, int v) {
    int pb, lb;
    for (pb = 1, lb = 0; pb; lb = pb, pb = b[pb].nxt)
        if (b[pb].siz < p)
            p -= b[pb].siz;
        else
            break;
    (!pb) && (pb = lb, p += b[pb].siz);
    for (int i = b[pb].siz; i >= p; --i) b[pb].a[i + 1] = b[pb].a[i];
    b[pb].a[p] = v, Trie::insert(v, 1, b[pb].rt), b[pb].val &= { v, 0 },
    ((++b[pb].siz) >= B) && (split(pb), true);
}
inline void remove(int p) {
    for (int pb = 1, lb = 1, v; pb; lb = pb, pb = b[pb].nxt)
        if (b[pb].siz >= p) {
            Trie::insert(v = b[pb].a[p], -1, b[pb].rt);
            for (int j = p; j <= b[pb].siz; ++j) b[pb].a[j] = b[pb].a[j + 1];
            if (!(--b[pb].siz))
                return (void)(b[lb].nxt = b[pb].nxt);
            if (v >= b[pb].val.mx2)
                b[pb].maxize();
            return;
        } else
            p -= b[pb].siz;
}
inline void update(int p, int v) {
    for (int i = 1; i; i = b[i].nxt)
        if (b[i].siz >= p)
            return Trie::insert(b[i].a[p], -1, b[i].rt), b[i].a[p] = v, Trie::insert(v, 1, b[i].rt),
                                                         b[i].maxize();
        else
            p -= b[i].siz;
}
inline int secmax(int L, int R) {
    SecMax res;
    for (int pb = 1, ps = 0, l, r; pb; ps += b[pb].siz, pb = b[pb].nxt) {
        l = L - ps, r = R - ps;
        if (l < 1 && r < 1)
            break;
        else if (l > b[pb].siz && r > b[pb].siz)
            continue;
        l = max(l, 1), r = min(b[pb].siz, r);
        if (l == 1 && r == b[pb].siz)
            res &= b[pb].val;
        else
            for (int j = l; j <= r; ++j) res &= { b[pb].a[j], 0 };
    }
    return res.mx2;
}
inline int query(int L, int R) {
    int res = 0;
    for (int pb = 1, s = secmax(L, R), ps = 0, l, r; pb; ps += b[pb].siz, pb = b[pb].nxt) {
        l = L - ps, r = R - ps;
        if (l < 1 && r < 1)
            break;
        else if (l > b[pb].siz && r > b[pb].siz)
            continue;
        l = max(l, 1), r = min(b[pb].siz, r);
        if (l == 1 && r == b[pb].siz)
            res = max(res, Trie::query(s, b[pb].rt));
        else
            for (int j = l; j <= r; ++j) res = max(res, s ^ b[pb].a[j]);
    }
    return res;
}
int main() {
    read(n), read(Q);
    for (int i = 1, x; i <= n; ++i) read(x), insert(i, x);
    char op;
    int x, y, ans = 0;
    while (Q--) {
        op = getchar();
        while (op < 'A' || op > 'Z') op = getchar();
        read(x), x = (x + ans) % n + 1;
        if (op == 'I')
            read(y), y = (y + ans) & 1048575, insert(x, y), ++n;
        else if (op == 'D')
            remove(x), --n;
        else if (op == 'C')
            read(y), y = (y + ans) & 1048575, update(x, y);
        else
            read(y), y = (y + ans) % n + 1, printf("%d\n", ans = query(min(x, y), max(x, y)));
    }
    return 0;
}